
/*
    连接管理模块
    通过连接创建信道
*/

#ifndef __M_CONN_H__
#define _MM_CONN_H__
#include "mq_channel.hpp"

namespace xgmq
{
    class Connection
    {
    public:
        using ptr=std::shared_ptr<Connection>;
        Connection(const VirtualHost::ptr &host,
                   const muduo::net::TcpConnectionPtr &conn,
                   const ProtobufCodecPtr &codec,
                   const ConsumerManager::ptr &cmp,
                   const ThreadPool::ptr &pool)
            : _host(host), _conn(conn), _codec(codec), _cmp(cmp), _pool(pool) 
            ,_channels(std::make_shared<ChannelManager>()){}
        // 创建信道
        void openChannel(const openChannelRequestPtr &req)
        {
            bool ret = _channels->openChannel(req->cid(),
                                              _host, _conn, _codec, _cmp, _pool);
            if (ret == false)
            {
                return basicResopnse(false, req->cid(), req->rid());
            }
            return basicResopnse(true, req->cid(), req->rid());
        }
        // 关闭信道
        void closeChannel(const closeChannelRequestPtr &req)
        {
            _channels->closeChannel(req->cid());
            return basicResopnse(true, req->cid(), req->rid());
        }
        Channel::ptr getChannel(const std::string& cid)
        {
            return _channels->selectChannel(cid);
        }
    private:
        void basicResopnse(bool ok, const std::string &cid, const std::string &rid)
        {
            basicCommonResponse resp;
            resp.set_ok(ok);
            resp.set_cid(cid);
            resp.set_rid(rid);
            _codec->send(_conn, resp);
        }

    private:
        VirtualHost::ptr _host;             // 虚拟机句柄，包含了交换机，队列，绑定关系，消息等模块
        muduo::net::TcpConnectionPtr _conn; // 连接管理
        ProtobufCodecPtr _codec;            // 协议处理句柄
        ConsumerManager::ptr _cmp;          // 消费者管理句柄
        ThreadPool::ptr _pool;                // 线程池
        // 这样多个信道公用一条连接，一个协议处理句柄，一个线程池，一个消费者管理句柄
        ChannelManager::ptr _channels;
    };

    //连接管理
    class ConnectionManager
    {
        public:
            using ptr=std::shared_ptr<ConnectionManager>;
            ConnectionManager(){}
            //创建一个连接
            void newConnection(const VirtualHost::ptr &host,
                   const muduo::net::TcpConnectionPtr &conn,
                   const ProtobufCodecPtr &codec,
                   const ConsumerManager::ptr &cmp,
                   const ThreadPool::ptr &pool)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                if(_conns.find(conn)!=_conns.end())
                {
                    return;
                }
                Connection::ptr self=std::make_shared<Connection>(host,conn,codec,cmp,pool);
                _conns.insert(std::make_pair(conn,self));
            }
            //删除连接
            void deleteConnection(const muduo::net::TcpConnectionPtr &conn)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                _conns.erase(conn);
            }
            //获取连接
            Connection::ptr getConnection(const muduo::net::TcpConnectionPtr &conn)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it=_conns.find(conn);
                if(it==_conns.end())
                {
                    return Connection::ptr();
                }
                return it->second;
            }
        private:
            std::mutex _mutex;
            std::unordered_map<muduo::net::TcpConnectionPtr,Connection::ptr> _conns;
    };
}
#endif